package main

import (
	"flag"
	"fmt"
	"io"
	"mssqltools/common"
	"os"
	"strings"

	"gorm.io/driver/sqlserver"
	"gorm.io/gorm"
	// "github.com/jinzhu/gorm"
	// _ "github.com/jinzhu/gorm/dialects/mssql"
)

//go run main.go -t 表名

func main() {
	//运行命令go run main.go -t 表名
	createModel()
}
func createModel() {
	// var host string
	// var user string
	// var pass string
	// var database string
	var table string
	//var pack string
	// 端口
	//var port string

	// flag.StringVar(&host, "h", "", "数据库地址")
	// flag.StringVar(&pass, "p", "", "密码")
	// flag.StringVar(&user, "u", "", "用户")
	// flag.StringVar(&database, "d", "", "数据库")
	flag.StringVar(&table, "t", "", "表名")
	//flag.StringVar(&port, "P", "", "端口")
	//flag.StringVar(&pack, "k", "", "端口")
	// 解析
	flag.Parse()
	// dsn := fmt.Sprintf(
	// 	"%s:%s@tcp(%s)/%s?parseTime=True&loc=Local",
	// 	user,
	// 	pass,
	// 	host,
	// 	database,
	// )
	conf := common.GetConfig()
	dsn := fmt.Sprintf("server=%s;port=%d;database=%s;user id=%s;password=%s", conf.DbConnect.Server, conf.DbConnect.Port, conf.DbConnect.Database, conf.DbConnect.User, conf.DbConnect.Password)
	db, err := gorm.Open(sqlserver.Open(dsn), &gorm.Config{})
	//db, err := gorm.Open("mssql", dsn) //gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		fmt.Println(err)
	}
	type Field struct {
		Field string `gorm:"column:Field"`
		Type  string `gorm:"column:Type"`
		//Comment string `gorm:"column:Comment"`
	}
	var fieldObj []Field
	packageName := fmt.Sprintf("package %s\n\n", "models") //"pack")
	structName := toUp(table)
	sns := fmt.Sprintf("type %s struct {", structName)
	file := packageName + sns
	sql := fmt.Sprintf("SELECT TABLE_NAME,  COLUMN_NAME as Field, DATA_TYPE as Type from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='%s';", table)
	db.Raw(sql).Scan(&fieldObj)
	for _, value := range fieldObj {
		//f := fmt.Sprintf("\n\t%s %s `json:\"%s\"` // %s ", toUp(value.Field), getType(value.Type), value.Field, value.Comment)
		f := fmt.Sprintf("\n\t%s %s `json:\"%s\" gorm:\"column:%s\"`", toUp(value.Field), getType(value.Type), value.Field, strings.ToLower(string(value.Field)))
		file = file + f
	}
	sne := "\n}"
	file = file + sne
	tableName := fmt.Sprintf("\n\nfunc (%s) TableName() string {\n\treturn \"%s\"\n}", structName, table)
	file = file + tableName
	fileName := fmt.Sprintf("models/%s.go", strings.ToLower(structName))
	fileInfo, er := os.Stat(fileName)
	if er == nil {
		// 存在就是不允许覆盖
		if fileInfo.Size() != 0 {
			fmt.Println("文件已存在！")
			return
		}
	}

	f, e := os.Create(fileName)
	if e != nil {
		fmt.Println("打开文件错误", e)
		return
	}
	_, we := io.WriteString(f, file)
	if we != nil {
		fmt.Println("写入文件错误", we)
		return
	}

}
func toUp(field string) string {
	var nextUp bool
	str := ""
	for key, value := range field {
		if key == 0 {
			str = str + strings.ToUpper(string(value))
			continue
		}
		if string(value) == "_" {
			nextUp = true
			continue
		}
		if nextUp {
			str = str + strings.ToUpper(string(value))
			nextUp = false
		} else {
			str = str + string(value)
		}
	}

	return str

}

func getType(typeString string) string {

	// i := strings.Index(typeString, "(")
	// if i < 0 {
	// 	i = len(typeString) - 1
	// }

	// t := typeString[:i]
	m := map[string]string{
		"bit":              "bool",
		"tinyint":          "int8",
		"smallint":         "int16",
		"int":              "int32",
		"bigint":           "int64",
		"float":            "float32",
		"real":             "float64",
		"money":            "float64",
		"smallmoney":       "float64",
		"decimal":          "float64",
		"numeric":          "float64",
		"char":             "string",
		"varchar":          "string",
		"text":             "string",
		"nchar":            "string",
		"nvarchar":         "string",
		"ntext":            "string",
		"datetime":         "time.Time",
		"smalldatetime":    "time.Time",
		"uniqueidentifier": "mssql.UniqueIdentifier",
		//Mysql
		// "tinyint":    "int64",
		// "smallint":   "int64",
		// "mediumint":  "int64",
		// "int":        "int64",
		// "bigint":     "int64",
		// "float":      "float64",
		// "decimal":    "string",
		// "bit":        "string",
		// "year":       "string",
		// "time":       "string",
		// "date":       "string",
		// "datetime":   "string",
		// "timestamp":  "string",
		// "char":       "string",
		// "varchar":    "string",
		// "tinytext":   "string",
		// "text":       "string",
		// "mediumtext": "string",
		// "longtext":   "string",
		// "enum":       "string",
		// 其他类型默认转字符
	}
	fmt.Println(typeString)
	if val, ex := m[typeString]; ex {
		return val
	} else {
		return "string"
	}
}
